package com.ybwh.springboot1.conf;

import java.io.IOException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.TypeMismatchException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.servlet.HandlerExceptionResolver;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.NoHandlerFoundException;

import com.alibaba.fastjson.JSON;
import com.ybwh.springboot1.common.ReturnT;

/**
 * common exception resolver
 *
 * @author fan
 */
@Configuration
@Order(-1000)
public class WebExceptionResolver implements HandlerExceptionResolver {
	private static transient Logger logger = LoggerFactory.getLogger(WebExceptionResolver.class);

	@Override
	public ModelAndView resolveException(HttpServletRequest request, HttpServletResponse response, Object handler,
			Exception ex) {
		logger.error("WebExceptionResolver:{}", ex);

		if (ex instanceof NoHandlerFoundException) {
			NoHandlerFoundException e = (NoHandlerFoundException) ex;
			ModelAndView mv = new ModelAndView("/404");
			mv.addObject("exceptionMsg",
					"404  url not found!!,request type is " + e.getHttpMethod() + ",url is " + e.getRequestURL());
			return mv;
		}

		// if json
		boolean isJson = false;
		HandlerMethod method = (HandlerMethod) handler;
		ResponseBody responseBody = method.getMethodAnnotation(ResponseBody.class);
		if (responseBody != null) {
			isJson = true;
		}

		// response
		ModelAndView mv = new ModelAndView();
		if (isJson) {
			try {
				// error result
				ReturnT<Object> resp = new ReturnT<>(ReturnT.FAIL_CODE, getExceptionMessage(ex), null);
				response.setContentType("application/json;charset=utf-8");
				response.getWriter().print(JSON.toJSONString(resp));
			} catch (IOException e) {
				logger.error(e.getMessage(), e);
			}
			return mv;
		} else {
			mv.addObject("exceptionMsg", getExceptionMessage(ex));
			if (ex instanceof NoHandlerFoundException) {
				mv.setViewName("/404");
			} else {
				mv.setViewName("/500");
			}

			return mv;
		}
	}

	/**
	 * 获取异常信息
	 * 
	 * @param cause
	 * @return
	 */
	private String getExceptionMessage(Throwable cause) {
		if (cause instanceof MissingServletRequestParameterException) {
			MissingServletRequestParameterException e1 = (MissingServletRequestParameterException) cause;
			return " miss parameters,name=[" + e1.getParameterName() + "],type=[" + e1.getParameterType() + "]";
		}

		if (cause instanceof TypeMismatchException) {
			TypeMismatchException e2 = (TypeMismatchException) cause;
			return "param type  error, required type is[" + e2.getRequiredType() + "],actual value is [" + e2.getValue()
					+ "].\n";
		}

		if (cause instanceof HttpRequestMethodNotSupportedException) {
			HttpRequestMethodNotSupportedException e = (HttpRequestMethodNotSupportedException) cause;
			return "HTTP request type error!! required type is " + e.getSupportedHttpMethods() + ",but your type is "
					+ e.getMethod();
		}
		if (cause instanceof NoHandlerFoundException) {
			NoHandlerFoundException e = (NoHandlerFoundException) cause;
			return "404  url not found!!,request type is " + e.getHttpMethod() + ",url is " + e.getRequestURL();
		}

		if (cause instanceof MultipartException) {
			MultipartException e = (MultipartException) cause;
			return "upload file erorr!! " + ExceptionUtils.getStackTrace(e);
		}

		return ExceptionUtils.getStackTrace(cause);
	}

}